using System;
using System.Collections;
using AopAlliance.Intercept;
using Sedna.Core.Event.Parsers;
using log4net;

namespace Sedna.Core.Event
{
    public class EventInterceptor : IMethodInterceptor
    {
        private static ILog LOG = LogManager.GetLogger(typeof(EventInterceptor));

        private IEventHandlerRegistry eventHandlerRegistry;
        
        public IEventHandlerRegistry EventHandlerRegistry
        {
            set { eventHandlerRegistry = value; }
        }

        public object Invoke(IMethodInvocation invocation)
        {
            /* Events will be sent if invocation proceeds successfully */
            Object result = invocation.Proceed();

            //IList events = new ArrayList();
            foreach (EventfulAttribute eventfulAttribute in GetEventfulAttributes(invocation))
            {
                if (eventHandlerRegistry.CanHandle(eventfulAttribute.Name))
                {
                    #region Log Debug

                    if (LOG.IsDebugEnabled)
                    {
                        LOG.Debug(String.Format("Event {0} is handling", eventfulAttribute.Name));
                    }

                    #endregion

                    if (eventHandlerRegistry.HandleEvent(eventfulAttribute, invocation, result))
                    {
                        #region Log Debug

                        if (LOG.IsDebugEnabled)
                        {
                            LOG.Debug(String.Format("Event {0} handled", eventfulAttribute.Name));
                        }

                        #endregion
                    }
                    else
                    {
                        #region Log Debug

                        if (LOG.IsDebugEnabled)
                        {
                            LOG.Debug(String.Format("Event {0} was not handled", eventfulAttribute.Name));
                        }

                        #endregion
                    }
                        
                }
                else
                {
                    #region Log Debug

                    if (LOG.IsDebugEnabled)
                    {
                        LOG.Debug(String.Format("Event {0} was not handled", eventfulAttribute.Name));
                    }

                    #endregion
                }

                #region Log Debug

                if (LOG.IsDebugEnabled)
                {
                    LOG.Debug(String.Format("Event {0} has been generated", eventfulAttribute.Name));
                }
            
                #endregion

            }

            return result;
        }
        
        private bool IsEventful(IMethodInvocation invocation)
        {
            Object[] attributes = invocation.StaticPart.GetCustomAttributes(typeof(EventfulAttribute), false);
            return (attributes != null && attributes.Length > 0);
        }
        
        private EventfulAttribute[] GetEventfulAttributes(IMethodInvocation invocation)
        {
            return (IsEventful(invocation) 
                        ? (EventfulAttribute[])invocation.StaticPart.GetCustomAttributes(typeof(EventfulAttribute), false) 
                        : new EventfulAttribute[0]);
        }
        
    }
}
